package jiang.jredis.channel;

import jiang.jredis.channel.annotation.Topic;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

import java.lang.reflect.Proxy;

/**
 * 创建Channel的工厂Bean
 */
public class ChannelFactoryBean<T> implements FactoryBean<T>, ApplicationContextAware {

    private final Class<T> type;
    private ApplicationContext applicationContext;

    /**
     * 构造方法注入需要创建的bean的类型
     */
    public ChannelFactoryBean(Class<T> type) {
        this.type = type;
    }

    /**
     * Aware属性注入
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    /**
     * 创建代理对象
     */
    @Override
    public T getObject() {

        // 获取Topic信息
        if (!type.isAnnotationPresent(Topic.class)) {
            throw new RuntimeException("没有添加@Topic注解的接口不可代理");
        }
        String topic = type.getAnnotation(Topic.class).value();

        // 获取注入对象
        RedisTemplate<String, Object> redisTemplate = applicationContext.getBean("redisTemplate", RedisTemplate.class);
        RedisMessageListenerContainer redisMessageListenerContainer = applicationContext.getBean(RedisMessageListenerContainer.class);

        // 创建代理对象
        return (T) Proxy.newProxyInstance(
                type.getClassLoader(),
                new Class[]{type},
                new ChannelInvocationHandler(topic, redisTemplate, redisMessageListenerContainer)
        );
    }

    /**
     * 获取对象类型
     */
    @Override
    public Class<T> getObjectType() {
        return type;
    }


}
